             package com.java.diagnostics.visualizer.memory.parser;
             
             import com.java.diagnostics.visualizer.data.DataLevel;
             import com.java.diagnostics.visualizer.data.SourceData;
             import com.java.diagnostics.visualizer.data.StructuredData;
             import com.java.diagnostics.visualizer.data.StructuredDataBuilder;
             import com.java.diagnostics.visualizer.data.TupleDataBuilder;
             import com.java.diagnostics.visualizer.data.axes.AxisPair;
             import com.java.diagnostics.visualizer.data.axes.XDataAxis;
             import com.java.diagnostics.visualizer.data.axes.YDataAxis;
             import com.java.diagnostics.visualizer.exceptions.GCAndMemoryVisualizerException;
             import com.java.diagnostics.visualizer.factory.DataFactory;
             import com.java.diagnostics.visualizer.factory.SourceDataFactory;
             import com.java.diagnostics.visualizer.impl.factory.LogFactory;
             import com.java.diagnostics.visualizer.memory.util.Messages;
             import com.java.diagnostics.visualizer.metadata.TupleMetaData;
             import com.java.diagnostics.visualizer.metadata.TupleMetaData.TableField;
             import com.java.diagnostics.visualizer.metadata.TupleMetaData.TableType;
             import com.java.diagnostics.visualizer.parser.vgc.sovereign.InstanceSovereignVGCParser;
             import com.java.diagnostics.visualizer.properties.OutputProperties;
             import com.java.diagnostics.visualizer.sources.Source;
             import java.io.BufferedReader;
             import java.text.MessageFormat;
             import java.util.Set;
             import java.util.logging.Level;
             import java.util.logging.Logger;
             import java.util.regex.Matcher;
             import java.util.regex.Pattern;
             
             public class InstancePsParser
               extends NativeMemoryParser
             {
               private static final int MILLISECONDS_PER_SECOND = 1000;
               public static final String PID_TEMPLATE = "pid {0}";
               private static final double BYTES_PER_KILOBYTE = 1024.0D;
               private static final String LINUX = "linux";
               protected double runningMemoryValue = 0.0D;
               
               protected boolean parsedZOSData = false;
               
               private static final String WHITESPACE = "\\s*";
               
               private static final String NUMBER = "([0-9][0-9]*)";
               
               private static final String CHAR = "([a-zA-Z0-9][a-zA-Z0-9]*)";
               
               private static final String[] HEADERS = { "ps interval =", "ps inteval =" };
               private static final Pattern LINE_PATTERN = Pattern.compile("\\s*([0-9][0-9]*)\\s*([0-9][0-9]*)\\s*([0-9][0-9]*)\\s*");
               
               private static final Pattern LINE_PATTERN_ZOS = Pattern.compile("\\s*([0-9][0-9]*)\\s*([0-9][0-9]*)\\s*");
               
               private static final Pattern LINE_PATTERN_JOBNAME_ZOS = Pattern.compile("\\s*([0-9][0-9]*)\\s*([0-9][0-9]*)\\s*([a-zA-Z0-9][a-zA-Z0-9]*)\\s*");
               
               private static final Pattern LINE_PATTERN_HEADER_JOBNAME_ZOS = Pattern.compile("\\s*PID\\s*VSZ\\s*JOBNAME\\s*");
               
               private static final Pattern INTERVAL_PATTERN = Pattern.compile(
                 "inte[r]*val\\s*=\\s*([0-9][0-9]*)", 2);
               
               private static final Pattern DATE_PATTERN = Pattern.compile("([0-9][0-9]*):([0-9][0-9]*):([0-9][0-9]*)\\s*([a-zA-Z0-9][a-zA-Z0-9]*)([a-zA-Z0-9][a-zA-Z0-9]*)([a-zA-Z0-9][a-zA-Z0-9]*)\\s*[0-9][0-9][0-9][0-9]");
               
               private static final Pattern SECONDS_PATTERN = Pattern.compile(
                 "timestamp\\s*=\\s*([0-9][0-9]*)", 2);
               
               private static final Logger TRACE = LogFactory.getTrace(InstanceSovereignVGCParser.class);
               
               private TupleDataBuilder inUseTuple;
               
               private TupleDataBuilder reservedAddressTuple;
               
               private double interval = -1.0D;
               private AxisPair memoryAxisPair;
               
               public SourceData parse(Source source, OutputProperties properties)
                 throws GCAndMemoryVisualizerException
               {
                 TRACE.entering(this.className, "parse");
                 
                 this.isGoodData = false;
                 
                 initialiseTuples();
                 this.xAxis = NativeMemoryAxes.prepareXAxis(source, properties);
                 
                 YDataAxis memoryAxis = 
                   NativeMemoryAxes.preparePagesMemoryAxis(properties);
                 
                 this.memoryAxisPair = factory.createAxisPair(this.xAxis, memoryAxis);
                 
                 this.inUseTuple = 
                   createTuple("NativeMemoryLabels.inuse", this.memoryAxisPair);
                 this.reservedAddressTuple = 
                   createTuple("NativeMemoryLabels.reserved", this.memoryAxisPair);
                 
                 this.inUseTuple.setTupleMetaData(new TupleMetaData(TupleMetaData.TableType.ARITHMETIC, 
                   new TupleMetaData.TableField[] { TupleMetaData.TableField.MEAN, TupleMetaData.TableField.MIN, TupleMetaData.TableField.MAX }));
                 this.reservedAddressTuple.setTupleMetaData(new TupleMetaData(
                   TupleMetaData.TableType.ARITHMETIC, new TupleMetaData.TableField[] { TupleMetaData.TableField.MEAN, 
                   TupleMetaData.TableField.MIN, TupleMetaData.TableField.MAX }));
                 
                 StructuredData platform = hiddenFactory.createStructuredData("platform", 
                   "platform");
                 ((StructuredDataBuilder)platform).put("1", "linux");
                 try
                 {
                   String variantIdentifier = source.getVariantIdentifier();
                   this.sourceData = 
                     SOURCE_DATA_FACTORY.createSourceData(variantIdentifier);
                   
                   BufferedReader reader = source.getSafeBufferedStreamReader();
                   String line = reader.readLine();
                   
                   while (line != null) {
                     handleLine(line, reader);
                     line = reader.readLine();
                   }
                   
                   if (this.isGoodData)
                   {
                     this.sourceData.addData(platform, DataLevel.VARIANT);
                     writeOutSourceData();
                   }
                   this.xAxis.updateNormalisation(this.sourceData);
                   reader.close();
                 } catch (Exception e) {
                   TRACE.log(Level.WARNING, e.toString(), e);
                   this.sourceData = null;
                 }
                 TRACE.exiting(this.className, "parse");
                 return this.sourceData;
               }
               
               private void handleLine(String line, BufferedReader reader)
               {
                 if (this.interval == -1.0D)
                 {
                   Matcher dateMatcher = DATE_PATTERN.matcher(line);
                   Matcher secondsMatcher = SECONDS_PATTERN.matcher(line);
                   if (dateMatcher.find()) {
                     this.runningTimestamp = LinuxDateConverter.parseDate(line);
                   } else if (secondsMatcher.find()) {
                     this.runningTimestamp = (Long.parseLong(secondsMatcher.group(1)) * 1000L);
                   } else {
                     Matcher intervalLine = INTERVAL_PATTERN.matcher(line);
                     if (intervalLine.find()) {
                       this.interval = 
                         (1000.0D * Double.parseDouble(intervalLine.group(1)));
                     }
                   }
                 }
                 
                 Matcher processLine = LINE_PATTERN.matcher(line);
                 if (processLine.matches())
                 {
                   if (this.interval > 0.0D) {
                     this.runningTimestamp += this.interval;
                   } else {
                     this.runningTimestamp += 1.0D;
                   }
                   this.xAxis.setX(this.runningTimestamp);
                   this.isGoodData = true;
                   
                   String pid = processLine.group(1);
                   this.sourceData.setVariantIdentifier(
                     MessageFormat.format("pid {0}", new String[] { pid }));
                   
                   double inUse = 1024.0D * 
                     Double.parseDouble(processLine.group(3));
                   double virtual = 1024.0D * 
                     Double.parseDouble(processLine.group(2));
                   this.inUseTuple.addDataPoint(inUse, this.currentComment);
                   this.reservedAddressTuple.addDataPoint(virtual, this.currentComment);
                 }
                 else
                 {
                   handleZOSLine(line, reader);
                 }
               }
               
               private void handleZOSLine(String line, BufferedReader reader)
               {
                 Matcher processLine = LINE_PATTERN_ZOS.matcher(line);
                 if (processLine.matches()) {
                   if (this.interval > 0.0D) {
                     this.runningTimestamp += this.interval;
                   } else {
                     this.runningTimestamp += 1.0D;
                   }
                   this.xAxis.setX(this.runningTimestamp);
                   this.isGoodData = true;
                   
                   String pid = processLine.group(1);
                   this.sourceData.setVariantIdentifier(
                     MessageFormat.format("pid {0}", new String[] { pid }));
                   
                   double virtual = 1024.0D * 
                     Double.parseDouble(processLine.group(2));
                   this.reservedAddressTuple.addDataPoint(virtual, this.currentComment);
                 }
                 else
                 {
                   processLine = LINE_PATTERN_HEADER_JOBNAME_ZOS.matcher(line);
                   if (processLine.matches())
                   {
                     if (this.interval > 0.0D) {
                       this.runningTimestamp += this.interval;
                     } else {
                       this.runningTimestamp += 1.0D;
                     }
                     
                     if (this.parsedZOSData) {
                       this.reservedAddressTuple.addDataPoint(this.runningMemoryValue, 
                         this.currentComment);
                       this.parsedZOSData = false;
                       
                       this.runningMemoryValue = 0.0D;
                     }
                   } else {
                     processLine = LINE_PATTERN_JOBNAME_ZOS.matcher(line);
                     if (processLine.matches()) {
                       this.xAxis.setX(this.runningTimestamp);
                       this.isGoodData = true;
                       
                       String pid = processLine.group(1);
                       this.sourceData.setVariantIdentifier(MessageFormat.format(
                         "pid {0}", new String[] { pid }));
                       
                       this.runningMemoryValue = (this.runningMemoryValue + 1024.0D * Double.parseDouble(processLine.group(2)));
                       this.parsedZOSData = true;
                     }
                   }
                 }
               }
               
               private TupleDataBuilder createTuple(String label, AxisPair axisPair) {
                 TupleDataBuilder tuple = factory.createTupleData(label, 
                   Messages.getString(label), axisPair);
                 this.allTuples.add(tuple);
                 
                 return tuple;
               }
               
               public static String[] getHeaders() {
                 return (String[])HEADERS.clone();
               }
             }


